﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="BaseWire.cs" company="pwasiewicz">
//   pwasiewicz
// </copyright>
// <summary>
//   Defines the BaseWire type.
// </summary>
// --------------------------------------------------------------------------------------------------------------------

namespace LogicSystem.Wires
{
    using System.Collections.Generic;
    using System.Linq;

    using LogicSystem.Interfaces;
    using LogicSystem.LogicGates;

    /// <summary>The base wire.</summary>
    public class Wire
    {
        /// <summary>
        /// Defines output gates of wire.
        /// </summary>
        private List<LogicGate> outputGates;

        /// <summary>
        /// Wire's current logic state.
        /// </summary>
        private bool state;

        /// <summary>Initializes a new instance of the <see cref="Wire"/> class.</summary>
        internal Wire()
        {
        }

        /// <summary>
        /// Gets or sets a value indicating whether this <see cref="Wire" /> is state.
        /// </summary>
        /// <value>
        ///   <c>true</c> if state; otherwise, <c>false</c>.
        /// </value>
        public bool State 
        {
            get
            {
                return this.state;
            }

            set
            {
                this.state = value;

                foreach (var gate in this.Gates)
                {
                    var totalTime = this.SimulatingEnvironment.TotalTime;
                    this.SimulatingEnvironment.PushIntoHeap(totalTime + gate.Latency, gate);
                }
            }
        }

        /// <summary>
        /// Gets or sets environment simulator.
        /// </summary>
        internal ISimulatingEnvironment<int, LogicGate> SimulatingEnvironment { get; set; }

        /// <summary>
        /// Gets the output gates.
        /// Initializes outputGate reference is null.
        /// </summary>
        private List<LogicGate> Gates
        {
            get
            {
                return this.outputGates ?? (this.outputGates = 
                                                    Enumerable.Empty<LogicGate>().ToList());
            }
        }

        /// <summary>
        /// Adds output gates to the wire.
        /// </summary>
        /// <param name="gates">Array of gates.</param>
        public void AddOutputGates(params LogicGate[] gates)
        {
            this.Gates.AddRange(gates);
        }

        /// <summary>
        /// Adds output gates to the wire.
        /// </summary>
        /// <param name="gates">Collection of gates.</param>
        public void AddOutputGates(IEnumerable<LogicGate> gates)
        {
            this.AddOutputGates(gates.ToArray());
        }
    }
}
